#!/bin/bash

# CU MR BULL API 部署脚本
# 用于自动化部署到生产环境

set -e

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 配置
APP_NAME="cu-mr-bull-api"
DOCKER_COMPOSE_FILE="docker-compose.yml"
ENV_FILE="backend/.env.production"
BACKUP_BEFORE_DEPLOY=${BACKUP_BEFORE_DEPLOY:-true}
RUN_TESTS=${RUN_TESTS:-true}
ZERO_DOWNTIME=${ZERO_DOWNTIME:-false}
# 兼容 docker compose v2 与旧版 docker-compose
DOCKER_COMPOSE_CMD=""

# 日志函数
log() {
    echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] ✓${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] ⚠${NC} $1"
}

log_error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ✗${NC} $1"
}

# 错误处理
error_exit() {
    log_error "$1"
    exit 1
}

# 检查必要的工具
check_dependencies() {
    log "Checking dependencies..."

    command -v docker >/dev/null 2>&1 || error_exit "Docker not found"

    # 兼容检测：优先使用 docker compose，其次 docker-compose
    if docker compose version >/dev/null 2>&1; then
        DOCKER_COMPOSE_CMD="docker compose"
    elif command -v docker-compose >/dev/null 2>&1; then
        DOCKER_COMPOSE_CMD="docker-compose"
    else
        error_exit "Docker Compose not found (install Docker Compose v2: 'docker compose')"
    fi

    if [ ! -f "$DOCKER_COMPOSE_FILE" ]; then
        error_exit "Docker Compose file not found: $DOCKER_COMPOSE_FILE"
    fi

    if [ ! -f "$ENV_FILE" ]; then
        error_exit "Environment file not found: $ENV_FILE"
    fi

    log_success "All dependencies found"
}

# 检查环境配置
check_environment() {
    log "Checking environment configuration..."

    # 检查必要的环境变量
    source "$ENV_FILE"

    if [ -z "$DB_HOST" ] || [ -z "$DB_NAME" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ]; then
        error_exit "Database configuration incomplete in $ENV_FILE"
    fi

    if [ -z "$JWT_SECRET" ] || [ "$JWT_SECRET" = "your-super-secure-jwt-secret-key-for-production" ]; then
        error_exit "JWT_SECRET not configured properly in $ENV_FILE"
    fi

    log_success "Environment configuration validated"
}

# 运行测试
run_tests() {
    if [ "$RUN_TESTS" = "true" ]; then
        log "Running tests..."

        cd backend
        if [ -f "package.json" ] && grep -q '"test"' package.json; then
            npm test || error_exit "Tests failed"
            log_success "All tests passed"
        else
            log_warning "No tests found, skipping"
        fi
        cd ..
    else
        log "Skipping tests (RUN_TESTS=false)"
    fi
}

# 备份数据库
backup_database() {
    if [ "$BACKUP_BEFORE_DEPLOY" = "true" ]; then
        log "Creating database backup before deployment..."

        if [ -f "scripts/backup.sh" ]; then
            chmod +x scripts/backup.sh
            $DOCKER_COMPOSE_CMD exec -T mysql bash -c "/backup.sh" || log_warning "Backup failed, continuing with deployment"
            log_success "Database backup completed"
        else
            log_warning "Backup script not found, skipping backup"
        fi
    else
        log "Skipping database backup (BACKUP_BEFORE_DEPLOY=false)"
    fi
}

# 构建镜像
build_images() {
    log "Building Docker images..."

    $DOCKER_COMPOSE_CMD build --no-cache app || error_exit "Failed to build application image"

    log_success "Docker images built successfully"
}

# 零停机部署
zero_downtime_deploy() {
    log "Performing zero-downtime deployment..."

    # 启动新容器
    $DOCKER_COMPOSE_CMD up -d --no-deps --scale app=2 app

    # 等待新容器健康检查通过
    log "Waiting for new containers to be healthy..."
    sleep 30

    # 检查健康状态
    if $DOCKER_COMPOSE_CMD ps app | grep -q "healthy"; then
        log_success "New containers are healthy"

        # 停止旧容器
        $DOCKER_COMPOSE_CMD up -d --no-deps --scale app=1 app

        log_success "Zero-downtime deployment completed"
    else
        log_error "New containers failed health check, rolling back..."
        $DOCKER_COMPOSE_CMD up -d --no-deps --scale app=1 app
        error_exit "Deployment failed"
    fi
}

# 标准部署
standard_deploy() {
    log "Performing standard deployment..."

    # 停止现有服务
    $DOCKER_COMPOSE_CMD down || true

    # 启动所有服务
    $DOCKER_COMPOSE_CMD up -d

    log_success "Standard deployment completed"
}

# 等待服务启动
wait_for_services() {
    log "Waiting for services to start..."

    # 等待应用启动
    for i in {1..60}; do
        if curl -f http://localhost:3000/health >/dev/null 2>&1; then
            log_success "Application is healthy"
            break
        fi

        if [ $i -eq 60 ]; then
            error_exit "Application failed to start within 60 seconds"
        fi

        sleep 1
    done
}

# 验证部署
validate_deployment() {
    log "Validating deployment..."

    # 检查容器状态
    if ! $DOCKER_COMPOSE_CMD ps | grep -q "Up"; then
        error_exit "Some containers are not running"
    fi

    # 检查API健康状态
    HEALTH_RESPONSE=$(curl -s http://localhost:3000/health || echo "failed")
    if echo "$HEALTH_RESPONSE" | grep -q '"status":"healthy"'; then
        log_success "API health check passed"
    else
        error_exit "API health check failed: $HEALTH_RESPONSE"
    fi

    # 检查数据库连接
    if $DOCKER_COMPOSE_CMD exec -T mysql mysqladmin ping -h localhost --silent; then
        log_success "Database connection verified"
    else
        error_exit "Database connection failed"
    fi

    log_success "Deployment validation completed"
}

# 清理旧镜像
cleanup() {
    log "Cleaning up old Docker images..."

    docker image prune -f || log_warning "Failed to clean up images"

    log_success "Cleanup completed"
}

# 显示部署信息
show_deployment_info() {
    log_success "Deployment completed successfully!"
    echo
    echo "=== Deployment Information ==="
    echo "Application: $APP_NAME"
    echo "Environment: production"
    echo "API URL: http://localhost:3000"
    echo "Health Check: http://localhost:3000/health"
    echo "API Documentation: http://localhost:3000/docs"
    echo
    echo "=== Running Services ==="
    $DOCKER_COMPOSE_CMD ps
    echo
    echo "=== Logs ==="
    echo "View logs with: $DOCKER_COMPOSE_CMD logs -f"
    echo "View app logs: $DOCKER_COMPOSE_CMD logs -f app"
    echo
}

# 主函数
main() {
    log "Starting deployment of $APP_NAME..."

    check_dependencies
    check_environment
    run_tests
    backup_database
    build_images

    if [ "$ZERO_DOWNTIME" = "true" ]; then
        zero_downtime_deploy
    else
        standard_deploy
    fi

    wait_for_services
    validate_deployment
    cleanup
    show_deployment_info

    log_success "Deployment process completed successfully!"
}

# 处理命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        --no-tests)
            RUN_TESTS=false
            shift
            ;;
        --no-backup)
            BACKUP_BEFORE_DEPLOY=false
            shift
            ;;
        --zero-downtime)
            ZERO_DOWNTIME=true
            shift
            ;;
        --help)
            echo "Usage: $0 [options]"
            echo "Options:"
            echo "  --no-tests        Skip running tests"
            echo "  --no-backup       Skip database backup"
            echo "  --zero-downtime   Use zero-downtime deployment"
            echo "  --help            Show this help message"
            exit 0
            ;;
        *)
            error_exit "Unknown option: $1"
            ;;
    esac
done

# 执行部署
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
    main "$@"
fi